package com.zero.service;

import com.zero.entity.*;
import com.zero.mapper.*;
import com.zero.util.DateUtils;
import com.zero.util.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

@Slf4j
@Service
public class StatisticService {

    @Autowired
    private PayMapper payMapper;

    @Autowired
    private PayTypeMapper payTypeMapper;

    @Autowired
    private IncomeMapper incomeMapper;

    @Autowired
    private IncomeTypeMapper incomeTypeMapper;

    @Autowired
    private InvestMapper investMapper;

    @Autowired
    private InvestTypeMapper investTypeMapper;

    @Autowired
    private LoanMapper loanMapper;

    @Autowired
    private FamilyMemberMapper familyMemberMapper;

    @Autowired
    private PayService payService;

    @Autowired
    private IncomeService incomeService;

    @Autowired
    private InvestService investService;

    @Autowired
    private  LoanService loanService;

    /**
     * 获得年度支出、收入、投资、借贷统计
     * @param map
     * @param request
     * @return
     */
    public Result getStatisticByYear(Map map, HttpServletRequest request) {
        if (map == null || map.get("year") == null || map.get("type") == null)
            return Result.fail("提供参数不完整");

        FamilyMember familyMember = (FamilyMember) request.getAttribute("familyMember");
        if (familyMember == null || familyMember.getId() == null)
            return Result.fail("获取不到用户数据");
        familyMember = familyMemberMapper.selectById(familyMember.getId());

        //获得年份的起止日期
        int year = Integer.parseInt(map.get("year") + "");
        Map yearStartAndEnd = DateUtils.getYearStartAndEnd(year);

        //设置查询参数
        HashMap<String, Object> param = new HashMap<>();
        param.putAll(yearStartAndEnd);

        //分别处理个人和家庭统计的情况
        if (Integer.parseInt(map.get("type") + "") == 0){
            log.info("查询个人今年情况");
            //设置查询参数
            param.put("memberId", familyMember.getId());
        }else{
            log.info("查询家庭今年情况");
            //设置查询参数
            param.put("familyId", familyMember.getFamilyId());
        }
        ArrayList<Map> yearData = getStatisticData(param);
        return Result.ok("获取"+year+"年度的数据成功", yearData);
    }

    /**
     * 查询指定时间段的支出、收入、投资、借贷的统计数据（累计操作）
     * @param param 包含起止时间，家庭id/个人id
     * @return
     */
    private ArrayList<Map> getStatisticData(Map param){
        if (param == null)
            return null;

        //查询支出、收入、投资、借贷结果
        List<Pay> pays = payMapper.selectByDate(param);
        List<Income> incomes = incomeMapper.selectByDate(param);
        List<Invest> invests = investMapper.selectByDate(param);
        List<Loan> loans = loanMapper.selectByDate(param);

        //统计支出数据
        HashMap<String, Object> payData = new HashMap<>();
        payData.put("name", "支出");
        BigDecimal payValue = new BigDecimal(0);
        for (Pay pay : pays) {
            payValue = payValue.add(pay.getMoney());
        }
        payData.put("value", payValue);

        //统计收入数据
        HashMap<String, Object> incomeData = new HashMap<>();
        incomeData.put("name", "收入");
        BigDecimal incomeValue = new BigDecimal(0);
        for (Income income : incomes) {
            incomeValue = incomeValue.add(income.getMoney());
        }
        incomeData.put("value", incomeValue);

        //统计投资数据
        HashMap<String, Object> investData = new HashMap<>();
        investData.put("name", "投资");
        BigDecimal investValue = new BigDecimal(0);
        for (Invest invest : invests) {
            investValue = investValue.add(invest.getMoney());
        }
        investData.put("value", investValue);

        //统计借贷数据
        HashMap<String, Object> loanData = new HashMap<>();
        loanData.put("name", "借贷");
        BigDecimal loanValue = new BigDecimal(0);
        for (Loan loan : loans) {
            loanValue = loanValue.add(loan.getMoney());
        }
        loanData.put("value", loanValue);

        ArrayList<Map> result = new ArrayList<>();
        result.add(payData);
        result.add(incomeData);
        result.add(investData);
        result.add(loanData);

        return result;
    }

    /**
     * 获取用户近五年的支出、收入、投资、借贷统计
     * @param map
     * @param request
     * @return
     */
    public Result getRecentFiveYear(Map map, HttpServletRequest request) {
        if (map == null || map.get("year") == null || map.get("type") == null)
            return Result.fail("提供参数不完整");

        FamilyMember familyMember = (FamilyMember) request.getAttribute("familyMember");
        if (familyMember == null || familyMember.getId() == null)
            return Result.fail("获取不到用户数据");
        familyMember = familyMemberMapper.selectById(familyMember.getId());

        int year = Integer.parseInt(map.get("year") + "") - 4;
        ArrayList<BigDecimal> payData = new ArrayList<>();
        ArrayList<BigDecimal> incomeData = new ArrayList<>();
        ArrayList<BigDecimal> investData = new ArrayList<>();
        ArrayList<BigDecimal> loanData = new ArrayList<>();
        if (Integer.parseInt(map.get("type") + "") == 0){
            log.info("查询个人近年情况");
            HashMap<String, Object> param = new HashMap<>();
            param.put("memberId", familyMember.getId());
            for (int i = 0; i < 5; i++) {
                Map yearStartAndEnd = DateUtils.getYearStartAndEnd(year);
                param.putAll(yearStartAndEnd);
                ArrayList<Map> yearData = getStatisticData(param);
                year++;
                for (Map temp : yearData) {
                    String name = (String) temp.get("name");
                    BigDecimal value = (BigDecimal) temp.get("value");
                    if (name.equals("支出")){
                        payData.add(value);
                    }
                    if (name.equals("收入")){
                        incomeData.add(value);
                    }
                    if (name.equals("投资")){
                        investData.add(value);
                    }
                    if (name.equals("借贷")){
                        loanData.add(value);
                    }
                }
            }
        }else{
            log.info("查询家庭近年情况");
            HashMap<String, Object> param = new HashMap<>();
            param.put("familyId", familyMember.getFamilyId());
            for (int i = 0; i < 5; i++) {
                Map yearStartAndEnd = DateUtils.getYearStartAndEnd(year);
                param.putAll(yearStartAndEnd);
                ArrayList<Map> yearData = getStatisticData(param);
                year++;
                for (Map temp : yearData) {
                    String name = (String) temp.get("name");
                    BigDecimal value = (BigDecimal) temp.get("value");

                    if (name.equals("支出")){
                        payData.add(value);
                    }
                    if (name.equals("收入")){
                        incomeData.add(value);
                    }
                    if (name.equals("投资")){
                        investData.add(value);
                    }
                    if (name.equals("借贷")){
                        loanData.add(value);
                    }
                }
            }
        }

        HashMap<String, Object> result = new HashMap<>();
        result.put("payData", payData);
        result.put("incomeData", incomeData);
        result.put("investData", investData);
        result.put("loanData", loanData);
        return Result.ok("获取近五年的数据成功", result);
    }

    /**
     * 查询家庭或个人一个季度的支出、收入、投资、借贷数据
     * @param map
     * @param request
     * @return
     */
    public Result getQuarterData(Map map, HttpServletRequest request) {
        //判断并用户信息
        FamilyMember familyMember = (FamilyMember) request.getAttribute("familyMember");
        if (familyMember == null || familyMember.getId() == null)
            return Result.fail("获取不到用户信息");
        familyMember = familyMemberMapper.selectById(familyMember.getId());

        //判断并获取参数
        if (map == null || map.get("year") == null || map.get("quarter") == null || map.get("type") == null)
            return Result.fail("获取查询信息失败");
        Integer year = Integer.parseInt( map.get("year") + "");
        Integer quarter = Integer.parseInt( map.get("quarter") + "");
        Integer type = Integer.parseInt(map.get("type") + "");

        //获得季度的起止日期
        Map<String, Calendar> quarterStartAndEnd = DateUtils.getQuarterStartAndEnd(year, quarter);
        HashMap<String, Object> param = new HashMap<>();
        param.putAll(quarterStartAndEnd);
        //个人数据查询, 以及家庭数据查询
        if (type == 0){
            param.put("memberId", familyMember.getId());
        }else if (type == 1){
            param.put("familyId", familyMember.getFamilyId());
        }

        ArrayList<Map> result = getStatisticData(param);

        return Result.ok("成功获得第"+ (quarter + 1)+"季度的数据", result);
    }


    /**
     * 获取两个季度的对比数据
     * @param map
     * @param request
     * @return
     */
    public Result getQuarterContrast(Map map, HttpServletRequest request){
        //判断并用户信息
        FamilyMember familyMember = (FamilyMember) request.getAttribute("familyMember");
        if (familyMember == null || familyMember.getId() == null)
            return Result.fail("获取不到用户信息");
        familyMember = familyMemberMapper.selectById(familyMember.getId());

        //判断并获取参数
        if (map == null || map.get("year") == null || map.get("quarter") == null || map.get("type") == null)
            return Result.fail("获取查询信息失败");
        Integer year = Integer.parseInt( map.get("year") + "");
        Integer quarter = Integer.parseInt( map.get("quarter") + "");
        Integer type = Integer.parseInt(map.get("type") + "");

        //获得本季度和上季度的起止日期
        Map<String, Calendar> quarterStartAndEnd = DateUtils.getQuarterStartAndEnd(year, quarter);
        Map<String, Calendar> lastQuarterStartAndEnd = DateUtils.getLastQuarterStartAndEnd(year, quarter);

        //设置两个季度的日期参数
        HashMap<String, Object> thisQuarterParam = new HashMap<>();
        HashMap<String, Object> lastQuarterParam = new HashMap<>();
        thisQuarterParam.putAll(quarterStartAndEnd);
        lastQuarterParam.putAll(lastQuarterStartAndEnd);
        //个人数据查询, 以及家庭数据查询
        if (type == 0){
            thisQuarterParam.put("memberId", familyMember.getId());
            lastQuarterParam.put("memberId", familyMember.getId());
        }else if (type == 1){
            thisQuarterParam.put("familyId", familyMember.getFamilyId());
            lastQuarterParam.put("familyId", familyMember.getFamilyId());
        }

        ArrayList<Map> thisQuarterData = getStatisticData(thisQuarterParam);
        ArrayList<Map> lastQuarterData = getStatisticData(lastQuarterParam);

        ArrayList<BigDecimal> thisData = new ArrayList<>();
        ArrayList<BigDecimal> lastData = new ArrayList<>();
        for (Map temp : thisQuarterData) {
            thisData.add(new BigDecimal(temp.get("value") + ""));
        }

        for (Map temp : lastQuarterData) {
            lastData.add(new BigDecimal(temp.get("value") + ""));
        }

        HashMap<String, Object> result = new HashMap<>();
        result.put("thisQuarter", thisData);
        result.put("lastQuarter", lastData);
        return Result.ok("查询两季度的对比数据成功", result);

    }

    /**
     * 获取当前月份的支出、收入、投资、借贷的情况（涉及分类）
     * @param map
     * @param request
     * @return
     */
    public Result getMonthData(Map map, HttpServletRequest request) {
        //判断并用户信息
        FamilyMember familyMember = (FamilyMember) request.getAttribute("familyMember");
        if (familyMember == null || familyMember.getId() == null)
            return Result.fail("获取不到用户信息");
        familyMember = familyMemberMapper.selectById(familyMember.getId());

        //判断并获取参数
        if (map == null || map.get("year") == null || map.get("month") == null || map.get("type") == null)
            return Result.fail("获取查询信息失败");
        int year = Integer.parseInt(map.get("year") + "");
        int month = Integer.parseInt(map.get("month") + "");
        int type = Integer.parseInt(map.get("type") + "");

        //获取月份的起止时间
        Map<String, Calendar> monthStartAndEnd = DateUtils.getMonthStartAndEnd(year, month);

        //构造查询的参数
        Map<String, Object> param = new HashMap<>();
        param.putAll(monthStartAndEnd);
        if (type == 0){
            param.put("memberId", familyMember.getId());
        }else{
            param.put("familyId", familyMember.getFamilyId());
        }

        List<Map<String, Object>> payData = getPayData(familyMember, param);
        List<Map<String, Object>> incomeData = getIncomeData(familyMember, param);
        List<Map<String, Object>> investData = getInvestData(familyMember, param);
        List<Map<String, Object>> loanData = getLoanData(param);

        HashMap<String, Object> result = new HashMap<>();
        result.put("payData", payData);
        result.put("incomeData", incomeData);
        result.put("investData", investData);
        result.put("loanData", loanData);

        return Result.ok("查询本月的统计数据成功", result);
    }

    /**
     * 获取登录者个人和家庭的当天财务情况
     * @param request
     * @return
     */
    public Result getTodayData(HttpServletRequest request){
        //获取用户信息
        FamilyMember familyMember = (FamilyMember) request.getAttribute("familyMember");
        if (familyMember == null || familyMember.getId() == null)
            return Result.fail("获取不到用户信息");
        familyMember = familyMemberMapper.selectById(familyMember.getId());

        //返回的数据格式
        Map<String, ArrayList<BigDecimal>> result = new HashMap<>();
        //个人的财务情况
        ArrayList<BigDecimal> member = new ArrayList<>();
        //家庭的财务情况
        ArrayList<BigDecimal> family = new ArrayList<>();

        //统计个人支出
        List<Pay> memberTodayPayData = payService.getMemberTodayData(familyMember.getId());
        BigDecimal total = new BigDecimal(0);
        for (Pay pay : memberTodayPayData) {
            total = total.add(pay.getMoney());
        }
        member.add(total);

        //统计家庭支出
        List<Pay> familyTodayPayData = payService.getFamilyTodayData(familyMember.getFamilyId());
        total = new BigDecimal(0);
        for (Pay pay : familyTodayPayData) {
            total = total.add(pay.getMoney());
        }
        family.add(total);

        //统计个人收入
        List<Income> memberTodayIncomeData = incomeService.getMemberTodayData(familyMember.getId());
        total = new BigDecimal(0);
        for (Income income : memberTodayIncomeData) {
            total = total.add(income.getMoney());
        }
        member.add(total);

        //统计家庭收入
        List<Income> familyTodayIncomeData = incomeService.getFamilyTodayData(familyMember.getFamilyId());
        total = new BigDecimal(0);
        for (Income income : familyTodayIncomeData) {
            total = total.add(income.getMoney());
        }
        family.add(total);

        //统计个人投资
        List<Invest> memberTodayInvestData = investService.getMemberTodayData(familyMember.getId());
        total = new BigDecimal(0);
        for (Invest invest : memberTodayInvestData) {
            total = total.add(invest.getMoney());
        }
        member.add(total);

        //统计家庭投资
        List<Invest> familyTodayInvestData = investService.getFamilyTodayData(familyMember.getFamilyId());
        total = new BigDecimal(0);
        for (Invest invest : familyTodayInvestData) {
            total = total.add(invest.getMoney());
        }
        family.add(total);

        //统计个人借贷
        List<Loan> memberTodayLoanData = loanService.getMemberTodayData(familyMember.getId());
        total = new BigDecimal(0);
        for (Loan loan : memberTodayLoanData) {
            total = total.add(loan.getMoney());
        }
        member.add(total);

        //统计家庭借贷
        List<Loan> familyTodayLoanData = loanService.getFamilyTodayData(familyMember.getFamilyId());
        total = new BigDecimal(0);
        for (Loan loan : familyTodayLoanData) {
            total = total.add(loan.getMoney());
        }
        family.add(total);

        log.info(member.toString());
        log.info(family.toString());

        result.put("member", member);
        result.put("family", family);

        return Result.ok(result);
    }


    /**
     * 获取各种支出类型的统计数据
     * @param familyMember
     * @param map
     * @return
     */
    private List<Map<String,Object>> getPayData(FamilyMember familyMember, Map<String, Object> map){
        if (familyMember == null || familyMember.getId() == null || familyMember.getFamilyId() == null)
            throw new RuntimeException("参数不合法");
        if (!map.containsKey("beginDate") || !map.containsKey("endDate"))
            throw new RuntimeException("参数不合法");
        if (!map.containsKey("memberId") && !map.containsKey("familyId"))
            throw new RuntimeException("参数不合法");

        //获取家庭的所有类型
        PayType payType = new PayType();
        payType.setFamilyId(familyMember.getFamilyId());
        List<PayType> payTypes = payTypeMapper.select(payType);

        //获取个人、家庭指定时间区段的所有支出数据
        List<Pay> pays = payMapper.selectByDate(map);

        ArrayList<Map<String, Object>> result = new ArrayList<>();
        for (PayType type : payTypes) {
            HashMap<String, Object> typeMap = new HashMap<>();
            typeMap.put("name", type.getName());
            BigDecimal value = new BigDecimal(0);
            for (Pay pay : pays) {
                if (pay.getTypeId() == type.getId()){
                    value = value.add(pay.getMoney());
                }
            }
            typeMap.put("value", value);
            result.add(typeMap);
        }

        return result;

    }

    /**
     * 获取各种收入类型的统计数据
     * @param familyMember
     * @param map
     * @return
     */
    private List<Map<String,Object>> getIncomeData(FamilyMember familyMember, Map<String, Object> map){
        if (familyMember == null || familyMember.getId() == null || familyMember.getFamilyId() == null)
            throw new RuntimeException("参数不合法");
        if (!map.containsKey("beginDate") || !map.containsKey("endDate"))
            throw new RuntimeException("参数不合法");
        if (!map.containsKey("memberId") && !map.containsKey("familyId"))
            throw new RuntimeException("参数不合法");

        //获取家庭的所有类型
        IncomeType incomeType = new IncomeType();
        incomeType.setFamilyId(familyMember.getFamilyId());
        List<IncomeType> incomeTypes = incomeTypeMapper.select(incomeType);

        //获取个人、家庭指定时间区段的所有支出数据
        List<Income> incomes = incomeMapper.selectByDate(map);

        ArrayList<Map<String, Object>> result = new ArrayList<>();
        for (IncomeType type : incomeTypes) {
            HashMap<String, Object> typeMap = new HashMap<>();
            typeMap.put("name", type.getName());
            BigDecimal value = new BigDecimal(0);
            for (Income income : incomes) {
                if (income.getTypeId() == type.getId()){
                    value = value.add(income.getMoney());
                }
            }
            typeMap.put("value", value);
            result.add(typeMap);
        }
        return result;
    }


    /**
     * 获取各种投资类型的统计数据
     * @param familyMember
     * @param map
     * @return
     */
    private List<Map<String,Object>> getInvestData(FamilyMember familyMember, Map<String, Object> map){
        if (familyMember == null || familyMember.getId() == null || familyMember.getFamilyId() == null)
            throw new RuntimeException("参数不合法");
        if (!map.containsKey("beginDate") || !map.containsKey("endDate"))
            throw new RuntimeException("参数不合法");
        if (!map.containsKey("memberId") && !map.containsKey("familyId"))
            throw new RuntimeException("参数不合法");

        //获取家庭的所有类型
        InvestType investType = new InvestType();
        investType.setFamilyId(familyMember.getFamilyId());
        List<InvestType> investTypes = investTypeMapper.select(investType);

        //获取个人、家庭指定时间区段的所有支出数据
        List<Invest> invests = investMapper.selectByDate(map);

        ArrayList<Map<String, Object>> result = new ArrayList<>();
        for (InvestType type : investTypes) {
            HashMap<String, Object> typeMap = new HashMap<>();
            typeMap.put("name", type.getName());
            BigDecimal value = new BigDecimal(0);
            for (Invest invest : invests) {
                if (invest.getTypeId() == type.getId()){
                    value = value.add(invest.getMoney());
                }
            }
            typeMap.put("value", value);
            result.add(typeMap);
        }
        return result;
    }


    /**
     * 获取借贷类型的统计数据
     * @param map
     * @return
     */
    private List<Map<String,Object>> getLoanData( Map<String, Object> map){
        if (!map.containsKey("beginDate") || !map.containsKey("endDate"))
            throw new RuntimeException("参数不合法");
        if (!map.containsKey("memberId") && !map.containsKey("familyId"))
            throw new RuntimeException("参数不合法");

        //获取个人、家庭指定时间区段的所有支出数据
        List<Loan> loans = loanMapper.selectByDate(map);

        ArrayList<Map<String, Object>> result = new ArrayList<>();

        HashMap<String, Object> borrowMap = new HashMap<>();
        HashMap<String, Object> lendMap = new HashMap<>();
        borrowMap.put("name", "借入");
        lendMap.put("name", "借出");
        BigDecimal borrowValue = new BigDecimal(0);
        BigDecimal lendValue = new BigDecimal(0);
        for (Loan loan : loans) {
            if (loan.getType() == 0)
                lendValue = lendValue.add(loan.getMoney());
            else
                borrowValue = borrowValue.add(loan.getMoney());
        }
        borrowMap.put("value", borrowValue);
        lendMap.put("value", lendValue);
        result.add(borrowMap);
        result.add(lendMap);

        return result;
    }

}
